package com.smart.community.work.controller;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.Result;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.smart.community.commons.result.ResultCode;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.work.dto.NotificationDTO;
import com.smart.community.work.service.NotificationService;
import com.smart.community.work.vo.NotificationVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 消息通知Controller
 *
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/work/notification")
@RequiredArgsConstructor
@Validated
@Tag(name = "消息通知管理", description = "消息通知相关接口")
public class NotificationController {

    private final NotificationService notificationService;

	@GetMapping("/page")
	@Operation(summary = "分页查询消息通知", description = "分页查询消息通知列表")
	public Result<PageResult<NotificationVO>> getNotificationPage(
			@Parameter(description = "当前页", example = "1") @RequestParam(defaultValue = "1") Integer current,
			@Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size,
			@Parameter(description = "接收人ID") @RequestParam(required = false) Long receiverId,
			@Parameter(description = "发送人ID") @RequestParam(required = false) Long senderId,
			@Parameter(description = "消息类型") @RequestParam(required = false) Integer type,
			@Parameter(description = "阅读状态") @RequestParam(required = false) Integer status,
			@Parameter(description = "是否紧急") @RequestParam(required = false) Boolean urgent,
			@Parameter(description = "是否置顶") @RequestParam(required = false) Boolean pinned,
			@Parameter(description = "查询开始日期") @RequestParam(required = false) String startDate,
			@Parameter(description = "查询结束日期") @RequestParam(required = false) String endDate,
			@Parameter(description = "接收人姓名") @RequestParam(required = false) String receiverName) {

		try {
			log.info("开始分页查询消息通知，当前页：{}，每页大小：{}，接收人ID：{}，发送人ID：{}，类型：{}", current, size, receiverId, senderId, type);

			// 参数校验
			if (current == null || current < 1) {
				return Result.fail("当前页必须大于0");
			}
			if (size == null || size < 1 || size > 100) {
				return Result.fail("每页大小必须在1-100之间");
			}

			// 日期范围校验
			if (startDate != null && endDate != null) {
				LocalDate start = LocalDate.parse(startDate);
				LocalDate end = LocalDate.parse(endDate);
				if (start.isAfter(end)) {
					return Result.fail("开始日期不能晚于结束日期");
				}
			}

			// 权限控制：获取当前用户信息
			Long currentUserId = SecurityUtils.getCurrentUserId();
			if (currentUserId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			// 权限控制：普通用户只能查看自己的消息通知
			if (receiverId != null && !receiverId.equals(currentUserId) && !SecurityUtils.hasRole("admin")) {
				return Result.fail("无权限查看其他用户的消息通知");
			}

			Map<String, Object> params = new java.util.HashMap<>();
			if (receiverId != null)
				params.put("receiverId", receiverId);
			if (senderId != null)
				params.put("senderId", senderId);
			if (type != null)
				params.put("type", type);
			if (status != null)
				params.put("status", status);
			if (urgent != null)
				params.put("urgent", urgent);
			if (pinned != null)
				params.put("pinned", pinned);
			if (startDate != null)
				params.put("startDate", startDate);
			if (endDate != null)
				params.put("endDate", endDate);
			if (receiverName != null)
				params.put("receiverName", receiverName);
			if (propertyCompanyId != null)
				params.put("propertyCompanyId", propertyCompanyId);

			IPage<NotificationVO> pageResult = notificationService.selectNotificationPage(current, size, params);
			PageResult<NotificationVO> result = new PageResult<NotificationVO>((int)pageResult.getCurrent(), (int)pageResult.getSize(), pageResult.getTotal(), pageResult.getRecords());
			log.info("分页查询消息通知成功，返回记录数：{}", result.getRecords().size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("分页查询消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("分页查询消息通知系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/{id}")
	@Operation(summary = "根据ID查询消息通知详情", description = "根据ID查询消息通知详情")
	public Result<NotificationVO> getNotificationById(
			@Parameter(description = "消息通知ID", required = true) @PathVariable @NotNull Long id) {

		try {
			log.info("开始根据ID查询消息通知详情，ID：{}", id);

			// 参数校验
			if (id == null || id <= 0) {
				return Result.fail("消息通知ID必须大于0");
			}

			// 权限控制：获取当前用户信息
			Long currentUserId = SecurityUtils.getCurrentUserId();
			if (currentUserId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			NotificationVO result = notificationService.selectNotificationById(id);
			if (result == null) {
				return Result.fail("消息通知不存在");
			}

			// 权限控制：普通用户只能查看自己的消息通知
			if (!result.getReceiverId().equals(currentUserId) && !SecurityUtils.hasRole("admin")) {
				return Result.fail("无权限查看其他用户的消息通知");
			}

			log.info("根据ID查询消息通知详情成功，ID：{}", id);
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("根据ID查询消息通知详情业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("根据ID查询消息通知详情系统异常，id={}，错误信息：{}", id, e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@PostMapping
	@Operation(summary = "新增消息通知", description = "新增消息通知")
	public Result<Boolean> addNotification(
			@Parameter(description = "消息通知DTO", required = true) @RequestBody @Valid NotificationDTO notificationDTO) {

		try {
			log.info("开始新增消息通知，发送人ID：{}，接收人ID：{}，标题：{}", notificationDTO.getSenderId(), notificationDTO.getReceiverId(),
					notificationDTO.getTitle());

			// 权限控制：获取当前用户信息
			Long currentUserId = SecurityUtils.getCurrentUserId();
			if (currentUserId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			// 权限控制：普通用户只能为自己发送消息通知
			if (notificationDTO.getSenderId() != null && !notificationDTO.getSenderId().equals(currentUserId)
					&& !SecurityUtils.hasRole("admin")) {
				return Result.fail("无权限为其他用户发送消息通知");
			}

			// 设置当前用户的物业公司ID和发送人ID
			notificationDTO.setPropertyCompanyId(propertyCompanyId);
			if (notificationDTO.getSenderId() == null) {
				notificationDTO.setSenderId(currentUserId);
			}

			// 业务规则验证
			validateNotificationDTO(notificationDTO);

			boolean result = notificationService.createNotification(notificationDTO);
			log.info("新增消息通知成功，发送人ID：{}，接收人ID：{}，结果：{}", notificationDTO.getSenderId(), notificationDTO.getReceiverId(),
					result);
			return Result.success("创建成功", result);
		} catch (BusinessException e) {
			log.warn("新增消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("新增消息通知系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("创建失败：" + e.getMessage());
		}
	}

	@PostMapping("/batch")
	@Operation(summary = "批量新增消息通知", description = "批量新增消息通知")
	public Result<Boolean> addNotificationBatch(
			@Parameter(description = "消息通知DTO", required = true) @RequestBody @Valid NotificationDTO notificationDTO) {

		try {
			log.info("开始批量新增消息通知，发送人ID：{}，接收人数量：{}，标题：{}", notificationDTO.getSenderId(),
					notificationDTO.getReceiverIds() != null ? notificationDTO.getReceiverIds().size() : 0,
					notificationDTO.getTitle());

			// 权限控制：获取当前用户信息
			Long currentUserId = SecurityUtils.getCurrentUserId();
			if (currentUserId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			// 设置当前用户的物业公司ID
			notificationDTO.setPropertyCompanyId(propertyCompanyId);

			boolean result = notificationService.batchCreateNotification(notificationDTO);
			log.info("批量新增消息通知成功，结果：{}", result);
			return Result.success("批量创建成功", result);
		} catch (BusinessException e) {
			log.warn("批量新增消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("批量新增消息通知系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("批量创建失败：" + e.getMessage());
		}
	}

	@PutMapping
	@Operation(summary = "更新消息通知", description = "更新消息通知")
	public Result<Boolean> updateNotification(
			@Parameter(description = "消息通知DTO", required = true) @RequestBody @Valid NotificationDTO notificationDTO) {
		try {
			log.info("开始更新消息通知，ID：{}", notificationDTO.getId());

			// 参数校验
			if (notificationDTO.getId() == null || notificationDTO.getId() <= 0) {
				return Result.fail("消息通知ID必须大于0");
			}

			// 权限控制：获取当前用户信息
			Long currentUserId = SecurityUtils.getCurrentUserId();
			if (currentUserId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			// 业务规则验证
			validateNotificationDTO(notificationDTO);

			boolean result = notificationService.updateNotification(notificationDTO);
			log.info("更新消息通知成功，ID：{}，结果：{}", notificationDTO.getId(), result);
			return Result.success("更新成功", result);
		} catch (BusinessException e) {
			log.warn("更新消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("更新消息通知系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("更新失败：" + e.getMessage());
		}
	}

	@DeleteMapping("/{id}")
	@Operation(summary = "删除消息通知", description = "删除消息通知")
	public Result<Boolean> deleteNotification(
			@Parameter(description = "消息通知ID", required = true) @PathVariable @NotNull Long id) throws Exception {
		try {
			log.info("开始删除消息通知，ID：{}", id);

			// 参数校验
			if (id == null || id <= 0) {
				return Result.fail("消息通知ID必须大于0");
			}

			boolean result = notificationService.deleteNotification(id);
			log.info("删除消息通知成功，ID：{}，结果：{}", id, result);
			return Result.success("删除成功", result);
		} catch (BusinessException e) {
			log.warn("删除消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("删除消息通知系统异常，ID：{}，错误信息：{}", id, e.getMessage(), e);
			return Result.fail("删除失败：" + e.getMessage());
		}
	}

	@DeleteMapping("/batch")
	@Operation(summary = "批量删除消息通知", description = "批量删除消息通知")
	public Result<Boolean> deleteNotificationBatch(
			@Parameter(description = "消息通知ID列表", required = true) @RequestBody @NotEmpty List<Long> ids)
			throws Exception {
		try {
			log.info("开始批量删除消息通知，IDs：{}", ids);

			// 参数校验
			if (ids == null || ids.isEmpty()) {
				return Result.fail("消息通知ID列表不能为空");
			}

			boolean result = notificationService.batchDeleteNotification(ids);
			log.info("批量删除消息通知成功，结果：{}", result);
			return Result.success("批量删除成功", result);
		} catch (BusinessException e) {
			log.warn("批量删除消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("批量删除消息通知系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("批量删除失败：" + e.getMessage());
		}
	}

	@GetMapping("/receiver/{receiverId}")
	@Operation(summary = "根据接收人ID查询消息通知", description = "根据接收人ID查询消息通知")
	public Result<List<NotificationVO>> getNotificationByReceiverId(
			@Parameter(description = "接收人ID", required = true) @PathVariable @NotNull Long receiverId)
			throws Exception {
		try {
			log.info("开始根据接收人ID查询消息通知，接收人ID：{}", receiverId);

			// 参数校验
			if (receiverId == null || receiverId <= 0) {
				return Result.fail("接收人ID必须大于0");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			List<NotificationVO> result = notificationService.selectNotificationByReceiverId(receiverId,
					propertyCompanyId);
			log.info("根据接收人ID查询消息通知成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("根据接收人ID查询消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("根据接收人ID查询消息通知系统异常，接收人ID：{}，错误信息：{}", receiverId, e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/sender/{senderId}")
	@Operation(summary = "根据发送人ID查询消息通知", description = "根据发送人ID查询消息通知")
	public Result<List<NotificationVO>> getNotificationBySenderId(
			@Parameter(description = "发送人ID", required = true) @PathVariable @NotNull Long senderId) throws Exception {
		try {
			log.info("开始根据发送人ID查询消息通知，发送人ID：{}", senderId);

			// 参数校验
			if (senderId == null || senderId <= 0) {
				return Result.fail("发送人ID必须大于0");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			List<NotificationVO> result = notificationService.selectNotificationBySenderId(senderId, propertyCompanyId);
			log.info("根据发送人ID查询消息通知成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("根据发送人ID查询消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("根据发送人ID查询消息通知系统异常，发送人ID：{}，错误信息：{}", senderId, e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/unread-count")
	@Operation(summary = "查询未读消息数量", description = "查询当前用户未读消息数量")
	public Result<Integer> getUnreadCount() {

		try {
			log.info("开始查询未读消息数量");

			// 权限控制：获取当前用户信息
			Long receiverId = SecurityUtils.getCurrentUserId();
			if (receiverId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			Integer result = notificationService.selectUnreadCount(receiverId, propertyCompanyId);
			log.info("查询未读消息数量成功，数量：{}", result);
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("查询未读消息数量业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("查询未读消息数量系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/unread-count/type/{type}")
	@Operation(summary = "查询指定类型的未读消息数量", description = "查询指定类型的未读消息数量")
	public Result<Integer> getUnreadCountByType(
			@Parameter(description = "消息类型", required = true) @PathVariable @NotNull Integer type) throws Exception {
		try {
			log.info("开始查询指定类型的未读消息数量，类型：{}", type);

			// 参数校验
			if (type == null) {
				return Result.fail("消息类型不能为空");
			}

			Long receiverId = SecurityUtils.getCurrentUserId();
			if (receiverId == null) {
				return Result.fail("用户未登录");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			Integer result = notificationService.selectUnreadCountByType(receiverId, propertyCompanyId, type);
			log.info("查询指定类型的未读消息数量成功，类型：{}，数量：{}", type, result);
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("查询指定类型的未读消息数量业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("查询指定类型的未读消息数量系统异常，类型：{}，错误信息：{}", type, e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/receiver/{receiverId}/date-range")
	@Operation(summary = "查询用户指定时间段的消息通知", description = "查询用户指定时间段的消息通知")
	public Result<List<NotificationVO>> getNotificationByReceiverIdAndDateRange(
			@Parameter(description = "接收人ID", required = true) @PathVariable @NotNull Long receiverId,
			@Parameter(description = "开始日期", required = true) @RequestParam @NotNull String startDate,
			@Parameter(description = "结束日期", required = true) @RequestParam @NotNull String endDate) throws Exception {
		try {
			log.info("开始查询用户指定时间段的消息通知，接收人ID：{}，开始日期：{}，结束日期：{}", receiverId, startDate, endDate);

			// 参数校验
			if (receiverId == null || receiverId <= 0) {
				return Result.fail("接收人ID必须大于0");
			}
			if (startDate == null || startDate.trim().isEmpty()) {
				return Result.fail("开始日期不能为空");
			}
			if (endDate == null || endDate.trim().isEmpty()) {
				return Result.fail("结束日期不能为空");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			LocalDate start = LocalDate.parse(startDate);
			LocalDate end = LocalDate.parse(endDate);
			if (start.isAfter(end)) {
				return Result.fail("开始日期不能晚于结束日期");
			}

			List<NotificationVO> result = notificationService.selectNotificationByReceiverIdAndDateRange(receiverId,
					propertyCompanyId, start, end);
			log.info("查询用户指定时间段的消息通知成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("查询用户指定时间段的消息通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("查询用户指定时间段的消息通知系统异常，接收人ID：{}，错误信息：{}", receiverId, e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/urgent")
	@Operation(summary = "查询紧急消息", description = "查询当前用户的紧急消息")
	public Result<List<NotificationVO>> getUrgentNotifications() throws Exception {
		try {
			log.info("开始查询紧急消息");

			Long receiverId = SecurityUtils.getCurrentUserId();
			if (receiverId == null) {
				return Result.fail("用户未登录");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			List<NotificationVO> result = notificationService.selectUrgentNotifications(receiverId, propertyCompanyId);
			log.info("查询紧急消息成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("查询紧急消息业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("查询紧急消息系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/pinned")
	@Operation(summary = "查询置顶消息", description = "查询当前用户的置顶消息")
	public Result<List<NotificationVO>> getPinnedNotifications() throws Exception {
		try {
			log.info("开始查询置顶消息");

			Long receiverId = SecurityUtils.getCurrentUserId();
			if (receiverId == null) {
				return Result.fail("用户未登录");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			List<NotificationVO> result = notificationService.selectPinnedNotifications(receiverId, propertyCompanyId);
			log.info("查询置顶消息成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("查询置顶消息业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("查询置顶消息系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@PostMapping("/{id}/read")
	@Operation(summary = "标记消息为已读", description = "标记消息为已读")
	public Result<Boolean> markAsRead(
			@Parameter(description = "消息通知ID", required = true) @PathVariable @NotNull Long id) throws Exception {
		try {
			log.info("开始标记消息为已读，ID：{}", id);

			// 参数校验
			if (id == null || id <= 0) {
				return Result.fail("消息通知ID必须大于0");
			}

			boolean result = notificationService.markAsRead(id);
			log.info("标记消息为已读成功，ID：{}，结果：{}", id, result);
			return Result.success("标记成功", result);
		} catch (BusinessException e) {
			log.warn("标记消息为已读业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("标记消息为已读系统异常，ID：{}，错误信息：{}", id, e.getMessage(), e);
			return Result.fail("标记失败：" + e.getMessage());
		}
	}

	@PostMapping("/batch/read")
	@Operation(summary = "批量标记消息为已读", description = "批量标记消息为已读")
	public Result<Boolean> markAsReadBatch(
			@Parameter(description = "消息通知ID列表", required = true) @RequestBody @NotEmpty List<Long> ids)
			throws Exception {
		try {
			log.info("开始批量标记消息为已读，IDs：{}", ids);

			// 参数校验
			if (ids == null || ids.isEmpty()) {
				return Result.fail("消息通知ID列表不能为空");
			}

			boolean result = notificationService.batchMarkAsRead(ids);
			log.info("批量标记消息为已读成功，结果：{}", result);
			return Result.success("批量标记成功", result);
		} catch (BusinessException e) {
			log.warn("批量标记消息为已读业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("批量标记消息为已读系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("批量标记失败：" + e.getMessage());
		}
	}

	@PostMapping("/all/read")
	@Operation(summary = "标记所有消息为已读", description = "标记当前用户所有消息为已读")
	public Result<Boolean> markAllAsRead() {

		try {
			log.info("开始标记所有消息为已读");

			// 权限控制：获取当前用户信息
			Long receiverId = SecurityUtils.getCurrentUserId();
			if (receiverId == null) {
				return Result.fail("用户未登录");
			}

			// 获取当前用户的物业公司ID
			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			boolean result = notificationService.markAllAsRead(receiverId, propertyCompanyId);
			log.info("标记所有消息为已读成功，结果：{}", result);
			return Result.success("标记成功", result);
		} catch (BusinessException e) {
			log.warn("标记所有消息为已读业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("标记所有消息为已读系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("标记失败：" + e.getMessage());
		}
	}

	@PostMapping("/{id}/pinned")
	@Operation(summary = "设置消息置顶", description = "设置消息置顶")
	public Result<Boolean> setPinned(@Parameter(description = "消息通知ID", required = true) @PathVariable @NotNull Long id,
			@Parameter(description = "是否置顶", required = true) @RequestParam @NotNull Boolean pinned) throws Exception {
		try {
			log.info("开始设置消息置顶，ID：{}，置顶：{}", id, pinned);

			// 参数校验
			if (id == null || id <= 0) {
				return Result.fail("消息通知ID必须大于0");
			}
			if (pinned == null) {
				return Result.fail("置顶状态不能为空");
			}

			boolean result = notificationService.setPinned(id, pinned);
			log.info("设置消息置顶成功，ID：{}，结果：{}", id, result);
			return Result.success("设置成功", result);
		} catch (BusinessException e) {
			log.warn("设置消息置顶业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("设置消息置顶系统异常，ID：{}，错误信息：{}", id, e.getMessage(), e);
			return Result.fail("设置失败：" + e.getMessage());
		}
	}

	@PostMapping("/{id}/urgent")
	@Operation(summary = "设置消息紧急", description = "设置消息紧急")
	public Result<Boolean> setUrgent(@Parameter(description = "消息通知ID", required = true) @PathVariable @NotNull Long id,
			@Parameter(description = "是否紧急", required = true) @RequestParam @NotNull Boolean urgent) throws Exception {
		try {
			log.info("开始设置消息紧急，ID：{}，紧急：{}", id, urgent);

			// 参数校验
			if (id == null || id <= 0) {
				return Result.fail("消息通知ID必须大于0");
			}
			if (urgent == null) {
				return Result.fail("紧急状态不能为空");
			}

			boolean result = notificationService.setUrgent(id, urgent);
			log.info("设置消息紧急成功，ID：{}，结果：{}", id, result);
			return Result.success("设置成功", result);
		} catch (BusinessException e) {
			log.warn("设置消息紧急业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("设置消息紧急系统异常，ID：{}，错误信息：{}", id, e.getMessage(), e);
			return Result.fail("设置失败：" + e.getMessage());
		}
	}

	@GetMapping("/statistics")
	@Operation(summary = "查询消息统计信息", description = "查询消息统计信息")
	public Result<Map<String, Object>> getNotificationStatistics(
			@Parameter(description = "开始日期", required = true) @RequestParam @NotNull String startDate,
			@Parameter(description = "结束日期", required = true) @RequestParam @NotNull String endDate) throws Exception {
		try {
			log.info("开始查询消息统计信息，开始日期：{}，结束日期：{}", startDate, endDate);

			// 参数校验
			if (startDate == null || startDate.trim().isEmpty()) {
				return Result.fail("开始日期不能为空");
			}
			if (endDate == null || endDate.trim().isEmpty()) {
				return Result.fail("结束日期不能为空");
			}

			Long propertyCompanyId = SecurityUtils.getCurrentPropertyCompanyId();
			if (propertyCompanyId == null) {
				return Result.fail("用户未关联物业公司");
			}

			LocalDate start = LocalDate.parse(startDate);
			LocalDate end = LocalDate.parse(endDate);
			if (start.isAfter(end)) {
				return Result.fail("开始日期不能晚于结束日期");
			}

			Map<String, Object> result = notificationService.selectNotificationStatistics(propertyCompanyId, start, end);
			log.info("查询消息统计信息成功");
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("查询消息统计信息业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("查询消息统计信息系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@GetMapping("/related/{relatedId}/{relatedType}")
	@Operation(summary = "根据关联业务查询消息", description = "根据关联业务查询消息")
	public Result<List<NotificationVO>> getNotificationByRelatedId(
			@Parameter(description = "关联业务ID", required = true) @PathVariable @NotNull Long relatedId,
			@Parameter(description = "关联业务类型", required = true) @PathVariable @NotNull String relatedType)
			throws Exception {
		try {
			log.info("开始根据关联业务查询消息，关联ID：{}，关联类型：{}", relatedId, relatedType);

			// 参数校验
			if (relatedId == null || relatedId <= 0) {
				return Result.fail("关联业务ID必须大于0");
			}
			if (relatedType == null || relatedType.trim().isEmpty()) {
				return Result.fail("关联业务类型不能为空");
			}

			List<NotificationVO> result = notificationService.selectNotificationByRelatedId(relatedId, relatedType);
			log.info("根据关联业务查询消息成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("根据关联业务查询消息业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("根据关联业务查询消息系统异常，关联ID：{}，错误信息：{}", relatedId, e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@DeleteMapping("/expired")
	@Operation(summary = "删除过期消息", description = "删除过期消息")
	public Result<Integer> deleteExpiredNotifications() throws Exception {
		try {
			log.info("开始删除过期消息");

			Integer result = notificationService.deleteExpiredNotifications();
			log.info("删除过期消息成功，删除数量：{}", result);
			return Result.success("删除成功", result);
		} catch (BusinessException e) {
			log.warn("删除过期消息业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("删除过期消息系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("删除失败：" + e.getMessage());
		}
	}

	@GetMapping("/types")
	@Operation(summary = "获取消息类型列表", description = "获取消息类型列表")
	public Result<List<Map<String, Object>>> getNotificationTypeList() throws Exception {
		try {
			log.info("开始获取消息类型列表");

			List<Map<String, Object>> result = notificationService.selectNotificationTypeList();
			log.info("获取消息类型列表成功，返回记录数：{}", result.size());
			return Result.success("查询成功", result);
		} catch (BusinessException e) {
			log.warn("获取消息类型列表业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("获取消息类型列表系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	@PostMapping("/system")
	@Operation(summary = "发送系统通知", description = "发送系统通知")
	public Result<Boolean> sendSystemNotification(
			@Parameter(description = "标题", required = true) @RequestParam @NotNull String title,
			@Parameter(description = "内容", required = true) @RequestParam @NotNull String content,
			@Parameter(description = "接收人ID列表", required = true) @RequestBody @NotEmpty List<Long> receiverIds,
			@Parameter(description = "消息类型", required = true) @RequestParam @NotNull Integer type,
			@Parameter(description = "关联业务ID") @RequestParam(required = false) Long relatedId,
			@Parameter(description = "关联业务类型") @RequestParam(required = false) String relatedType) throws Exception {
		try {
			log.info("开始发送系统通知，标题：{}，接收人数量：{}，类型：{}", title, receiverIds.size(), type);

			// 参数校验
			if (title == null || title.trim().isEmpty()) {
				return Result.fail("标题不能为空");
			}
			if (content == null || content.trim().isEmpty()) {
				return Result.fail("内容不能为空");
			}
			if (receiverIds == null || receiverIds.isEmpty()) {
				return Result.fail("接收人ID列表不能为空");
			}
			if (type == null) {
				return Result.fail("消息类型不能为空");
			}

			boolean result = notificationService.sendSystemNotification(title, content, receiverIds, type, relatedId,
					relatedType);
			log.info("发送系统通知成功，结果：{}", result);
			return Result.success("发送成功", result);
		} catch (BusinessException e) {
			log.warn("发送系统通知业务异常：{}", e.getMessage());
			return Result.fail(e.getMessage());
		} catch (Exception e) {
			log.error("发送系统通知系统异常，错误信息：{}", e.getMessage(), e);
			return Result.fail("发送失败：" + e.getMessage());
		}
	}

	/**
	 * 验证消息通知DTO的业务规则
	 * 
	 * @param notificationDTO 消息通知DTO
	 */
	private void validateNotificationDTO(NotificationDTO notificationDTO) {
		// 发送人ID校验
		if (notificationDTO.getSenderId() == null || notificationDTO.getSenderId() <= 0) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "发送人ID不能为空且必须大于0");
		}

		// 接收人ID校验
		if (notificationDTO.getReceiverId() == null || notificationDTO.getReceiverId() <= 0) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "接收人ID不能为空且必须大于0");
		}

		// 标题校验
		if (notificationDTO.getTitle() == null || notificationDTO.getTitle().trim().isEmpty()) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "消息标题不能为空");
		}

		if (notificationDTO.getTitle().length() > 200) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "消息标题不能超过200个字符");
		}

		// 内容校验
		if (notificationDTO.getContent() == null || notificationDTO.getContent().trim().isEmpty()) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "消息内容不能为空");
		}

		if (notificationDTO.getContent().length() > 2000) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "消息内容不能超过2000个字符");
		}

		// 消息类型校验
		if (notificationDTO.getType() == null) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "消息类型不能为空");
		}

		// 消息类型必须在有效范围内
		if (notificationDTO.getType() < 1 || notificationDTO.getType() > 10) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "消息类型必须在1-10之间");
		}

		// 阅读状态校验
		if (notificationDTO.getStatus() != null
				&& (notificationDTO.getStatus() < 0 || notificationDTO.getStatus() > 2)) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "阅读状态必须在0-2之间");
		}

		// 优先级校验
		if (notificationDTO.getPriority() != null
				&& (notificationDTO.getPriority() < 1 || notificationDTO.getPriority() > 5)) {
			throw new BusinessException(ResultCode.VALIDATION_FAILED.getCode(), "优先级必须在1-5之间");
		}
	}
}
